import {type EventBusReturn, useEventBus} from "@/utils/eventBus";
import {Cookie} from "@/utils/storage";
import {type EventMessageData, type FunctionCallback, type MsgConnectInfo, type SubscribeEventMessageResult, WebMessageType} from "./type";
import {webMessageServeAisleApi} from "@/api/zyApi";
import {onMounted, onUnmounted, onDeactivated, onActivated} from "vue";
//事件总线
const eventBus: EventBusReturn = useEventBus();

/**
 * WebMessage服务
 */
export class WebMessageServer {
    //通道是否已经关闭
    private isConnectClose: boolean = false;
    //是否连接成功
    private isConnectSuccess: boolean = false;
    //重新连接次数
    private timeConnect: number = 0;
    //是否可以重新连接通道
    private isReconnect: boolean = true;
    //通道
    private _webScoket?: WebSocket;
    //通道心跳计时调用
    private _timerHeartbeat?: any;
    //防止重复重连
    private lockReconnect: boolean = false;

    /**
     * 初始化服务
     * @constructor
     */
    async InitServer() {
        this.isReconnect = true;
        //开始连接服务器
        await this.ConnectHandle();
    }

    /**
     * 重新连接通道
     * @constructor
     * @private
     */
    private Reconnect() {
        if (!this.isReconnect) {
            return;
        }
        if (this.lockReconnect) {
            return;
        }
        this.lockReconnect = true;
        // lockReconnect加锁，防止onclose、onerror两次重连
        this.timeConnect++;
        const thisT = this;
        eventBus.emit("SubscribeAgainConnect", this.timeConnect);
        // 进行重连
        setTimeout(async () => {
            thisT.lockReconnect = false;
            await thisT.ConnectHandle();
        }, 3000);
    }

    /**
     * 开始连接服务器
     * @private
     */
    private async ConnectHandle() {
        console.log('开始')
        if (this.isConnectSuccess) {
            return;
        }
        let serverUrl = "";
        try {
            //开始获取
            const res = await webMessageServeAisleApi.GetServerResult({
                ErrorMessageMode: "none",
                IgnoreAuth: true
            });
            if (res == null) {
                this.Reconnect();
                return;
            }
            serverUrl = res.ServerUrl as any;
        } catch {
            this.Reconnect();
            return;
        }
        this._webScoket = new WebSocket(serverUrl);
        this._webScoket.onopen = () => {
            this.timeConnect = 0;
            this.isConnectClose = false;
            this.isConnectSuccess = true;
            this.SendData("connect", Cookie.getCookie("Authorization"));
        };
        this._webScoket.onclose = () => {
            //关闭计时心跳调用
            if (this._timerHeartbeat) {
                clearInterval(this._timerHeartbeat);
            }
            this.isConnectSuccess = false;
            if (!this.isConnectClose) {
                this.isConnectClose = true;
                eventBus.emit("SubscribeConnectClose", this.timeConnect);
            }
            this.Reconnect();
        };
        this._webScoket.onmessage = (e) => {
            //必须这样写,解决this指向问题
            this.HandleWebScoketMessage(e);
        };
    }


    /**
     * 收到通道消息
     * @param e
     * @constructor
     * @private
     */
    private HandleWebScoketMessage(e: MessageEvent) {
        //console.log(e);
        let arr = e.data.split("\u0000\u0000");
        if (arr.length == 2) {
            let commandId = arr[0];
            let body = arr[1];
            //通道认证
            if (commandId == "connectSuccess") {
                let loginInfo = JSON.parse(body);
                eventBus.emit("SubscribeConnectSuccess", loginInfo);
                this._timerHeartbeat = setInterval(() => {
                    this.SendPing();
                }, 1000 * 10);
                return;
            }
            if (commandId == "connectFail") {
                this.isReconnect = false;
                eventBus.emit("SubscribeConnectAuthFail", body);
                return;
            }
            return;
        }
        this.HandleEventMessage(e.data);


    }

    //处理收到事件消息数据
    private HandleEventMessage(data: string) {
        let arr = data.split("\u0000\u0001\u0000");

        if (arr.length != 3) {
            return;
        }
        let msgData: EventMessageData = {
            Type: arr[1],
            Message: arr[2]
        };
        eventBus.emit("cloud_event_message", msgData);
    }

    /**
     * 发送心跳
     * @constructor
     * @private
     */
    private SendPing() {
        if (this.isConnectSuccess) {
            this._webScoket?.send("\u0001\u0001\u0000\u0000");//发送4个字节
        } else {
            clearInterval(this._timerHeartbeat);
        }
    }

    /**
     * 发送数据
     * @param commandid 命令
     * @param data 数据
     * @constructor
     * @private
     */
    private SendData(commandid: string, data: string): void {
        if (this.isConnectSuccess) {
            this._webScoket?.send(commandid + "\u0000\u0000" + data);
        }
    }

    /**
     * 取消重新连接
     * @constructor
     */
    CancelReconnect(): void {
        this.isReconnect = false;
    }

    /**
     * 与服务器连接成功事件触发
     * @param callback
     * @constructor
     */
    SubscribeConnectSuccess(callback: FunctionCallback<MsgConnectInfo>): void {
        eventBus.on<MsgConnectInfo>("SubscribeConnectSuccess", data => {
            callback(data);
        });
    }

    /**
     * 与服务器连接断开
     * @param callback
     * @constructor
     */
    SubscribeConnectClose(callback: FunctionCallback<number>): void {
        eventBus.on<number>("SubscribeConnectClose", (data) => {
            callback(data);
        });
    }

    /**
     * 订阅与服务器连接授权失败
     * @param callback
     * @constructor
     */
    SubscribeConnectAuthFail(callback: FunctionCallback<string>): void {
        eventBus.on<string>("SubscribeConnectAuthFail", (data) => {
            callback(data);
        });
    }

    /**
     * 订阅消息
     * @param type 消息类型
     * @param callback 回调
     * @param isAutoOff 是否切换页面的时候自动关闭 默认开启
     * @constructor
     */
    SubscribeMessage(type: WebMessageType, callback: FunctionCallback<EventMessageData>, isAutoOff: boolean = true): SubscribeEventMessageResult {
        const action = (data: EventMessageData) => {
            if (data.Type == type.toString()) {
                callback(data);
            }
        }
        let isOn = false;
        const onAction = () => {
            if (isOn) {
                return;
            }
            eventBus.on<EventMessageData>("cloud_event_message", action);
            //console.log("订阅消息");
            isOn = true;
        };
        const offAction = () => {
            if (isOn == false) {
                return;
            }
            eventBus.off("cloud_event_message", action);
            //console.log("取消订阅消息", "2");
            isOn = false;
        }
        if (isAutoOff) {
            onMounted(() => {
                onAction();
            });
            onActivated(() => {
                onAction();
            });
            onDeactivated(() => {
                offAction();
            });
            onUnmounted(() => {
                offAction();
            });
        } else {
            onAction();
        }

        return {
            cancel() {
                offAction();
            }
        };
    }
};
